import hashlib
from Crypto import Random
from Crypto.Hash import SHA256
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from Crypto.PublicKey import RSA
import os
import base64
# from  util.singelMode  import singleton
# @singleton
class CCrypto:
    def __init__(self):
        pass 
    def __call__(self):
        return self
    @staticmethod
    def getAddressFromPublicKey(public_pem):
        '''
        public_pem  type 为：<class 'bytes'>  pem格式
        return   address type 为:<class 'str'>
        '''
        digest = SHA256.new()
        digest.update(public_pem)
        obj = hashlib.new('ripemd160', digest.digest())
        address= obj.hexdigest()
        return address


    @staticmethod
    def getAddressFromKeystr(keystr):
        '''
        keystr pem格式的字符串
        '''
        try:
            rsakey = RSA.importKey(keystr)
        except Exception:
            return ""
        else:
            public_pem = rsakey.publickey().exportKey()#public_pem  type 为：<class 'bytes'>
            #生成地址
            address = CCrypto.getAddressFromPublicKey(public_pem)
            return address

    @staticmethod
    def addKey(path,keyStr):
        if not os.path.exists(path):
            os.makedirs(path)
        try:
            rsakey = RSA.importKey(keyStr)
        except Exception:
            return False
        else:
            # 秘钥对的生成
            private_pem = rsakey.exportKey()#public_pem  type 为：<class 'bytes'>
            public_pem = rsakey.publickey().exportKey()#public_pem  type 为：<class 'bytes'>
            #生成地址
            address = CCrypto.getAddressFromPublicKey(public_pem)
            #--------------------------------------------生成公私钥对文件-----------------------------------------------------------
            privateKeyFile=os.path.join(path,address+'-private.pem')
            publickKeyFile=os.path.join(path,address+'-public.pem')
            with open(privateKeyFile, 'wb') as f:
                f.write(private_pem)
            with open(publickKeyFile, 'wb') as f:
                f.write(public_pem)
            return True
    @staticmethod
    def addKey(keyStr):
        try:
            rsakey = RSA.importKey(keyStr)
        except Exception:
            return None
        else:
            # 秘钥对的生成
            private_pem = rsakey.exportKey()#public_pem  type 为：<class 'bytes'>
            public_pem = rsakey.publickey().exportKey()#public_pem  type 为：<class 'bytes'>
            #生成地址
            address = CCrypto.getAddressFromPublicKey(public_pem)
            #--------------------------------------------生成公私钥对文件-----------------------------------------------------------
            result={
            'address':address,
            'publickey':public_pem.decode('utf-8'),
            'privatekey':private_pem.decode('utf-8')
            }
            return result

    @staticmethod
    def produceKey1(path):
        # path = "wallet"
        # 伪随机数生成器
        random_generator = Random.new().read

        # rsa算法生成实例
        rsa = RSA.generate(1024, random_generator)

        # 秘钥对的生成
        private_pem = rsa.exportKey()#public_pem  type 为：<class 'bytes'>
        public_pem = rsa.publickey().exportKey()#public_pem  type 为：<class 'bytes'>
        

        #生成地址
        address = CCrypto.getAddressFromPublicKey(public_pem)
    
        #--------------------------------------------生成公私钥对文件-----------------------------------------------------------
        privateKeyFile=os.path.join(path,address+'-private.pem')
        publickKeyFile=os.path.join(path,address+'-public.pem')
        with open(privateKeyFile, 'wb') as f:
            f.write(private_pem)
        with open(publickKeyFile, 'wb') as f:
            f.write(public_pem)
    @staticmethod
    def produceKey():
        # 伪随机数生成器
        random_generator = Random.new().read

        # rsa算法生成实例
        rsa = RSA.generate(1024, random_generator)

        # 秘钥对的生成
        private_pem = rsa.exportKey()#public_pem  type 为：<class 'bytes'>
        public_pem = rsa.publickey().exportKey()#public_pem  type 为：<class 'bytes'>
        #生成地址
        address = CCrypto.getAddressFromPublicKey(public_pem)
        result={
            'address':address,
            'publickey':public_pem.decode('utf-8'),
            'privatekey':private_pem.decode('utf-8')
        }
        return result
        

       
    @staticmethod
    def sign(data):
        # privateKeyFile=os.path.join(path,address+'-private.pem')
        # publickKeyFile=os.path.join(path,address+'-public.pem')
        privateKeyFile='test/he-private.pem'
        publickKeyFile='test/he-public.pem'
        with open(privateKeyFile) as f:
            key = f.read()
            rsakey = RSA.importKey(key)
            signer = Signature_pkcs1_v1_5.new(rsakey)
            digest = SHA256.new()
            digest.update(data.encode())
            sign = signer.sign(digest)
            signatureStr=bytes.decode(base64.b64encode(sign))
            # signatureStr=base64.b64encode(sign)
        with open(publickKeyFile) as f:
            publickey = f.read() 
            # rsakey = RSA.importKey(publickey)
            # public_pem = rsakey.publickey().exportKey(format="DER")
            # publickey=bytes.decode(base64.b64encode(public_pem))
        return signatureStr, publickey
    # @staticmethod
    # def signature(path,data,address):
    #     # path = "wallet"
    #     data=data.replace(": ",":")
    #     data=data.replace(", ",",")
    #     privateKeyFile=os.path.join(path,address+'-private.pem')
    #     publickKeyFile=os.path.join(path,address+'-public.pem')
    #     print(privateKeyFile)
    #     with open(privateKeyFile) as f:
    #         key = f.read()
    #         print(key.encode())
    #         rsakey = RSA.importKey(key)
    #         signer = Signature_pkcs1_v1_5.new(rsakey)
    #         digest = SHA256.new()
    #         digest.update(data.encode())
    #         sign = signer.sign(digest)
    #         signatureStr=bytes.decode(base64.b64encode(sign))
    #     with open(publickKeyFile) as f:
    #         publickey = f.read()  
    #     return signatureStr, publickey
    @staticmethod
    def signature(data,privatekey):
        data=data.replace(": ",":")
        data=data.replace(", ",",")
        rsakey = RSA.importKey(privatekey)
        signer = Signature_pkcs1_v1_5.new(rsakey)
        digest = SHA256.new()
        digest.update(data.encode())
        sign = signer.sign(digest)
        signatureStr=bytes.decode(base64.b64encode(sign))
        public_pem = rsakey.publickey().exportKey()
        publickey=public_pem.decode('utf-8')
        return signatureStr, publickey

    @staticmethod
    def verifySignature(data,signatureStr,publickey):
        '''
        @param data string 
        '''
        
        data=data.replace(": ",":")
        data=data.replace(", ",",")
        is_verify = False
        signature = signatureStr
        key = publickey
        rsakey = RSA.importKey(key)
        verifier = Signature_pkcs1_v1_5.new(rsakey)
        digest = SHA256.new()
        digest.update(data.encode())
        is_verify = verifier.verify(digest, base64.b64decode(signature))
        return is_verify
    @staticmethod
    def ifIsRightKeyString(keystr):
        try:
            rsakey = RSA.importKey(keystr)
        except Exception:
            return False
        else:
            return True
    @staticmethod
    def ifIsRightPublicKeyString(keystr):
        try:
            rsakey = RSA.importKey(keystr)
        except Exception:
            return False
        else:
            if rsakey.exportKey() == rsakey.publickey().exportKey():
                return True
            return False
    
    @staticmethod
    def ifIsRightPrivateKeyString(keystr):
        try:
            rsakey = RSA.importKey(keystr)
        except Exception:
            return False
        else:
            if rsakey.exportKey() != rsakey.publickey().exportKey():
                return True
            return False

# CCrypto.produceKey()     
# privatekey='-----BEGIN RSA PRIVATE KEY-----\nMIICXAIBAAKBgQCsJGBcD269EUIrMWgaCN+gNzl3FPM1G0rhzWYHBNXFQwKDi0Ye\nDfCIVq/4vurxQDTr5AKFPUktZkXf77A6ZCwUbWRC+D/agzh8XrgBe03fftwtGugr\nZC9OFwPOSxFc5TcrmEtyHPE8qIgve/aUYbMA9oZC5udy09PVHAnkloMX1QIDAQAB\nAoGBAI+WgDIKRWq73J++xIEC6dXweqST+xJPQ7T56aLtK4sxjAVBxSkIo5x2Aq7Q\nQZUe44XoWRnetw2Bg8N5YVwzdnfnMoAb34OdnpjMppd/px1GWFa2kf/MmEIWqHF1\nJ69tRDqT0y5vfc922vjb65bH9lL/iwovkmlzYu+30/NM7HLBAkEA/SFNOgftBb1B\nn8Zg/q7N2P5ig9Xcx5VEJe0D9oCJzJeUPeuiiMv6q1Kk9WaUj2KCDq5IC4B0D8y9\nNmhw3p7sqQJBAK4YAsdaIA+i5HOM+FtvU4Vz23kDReE+n7Ce3jKLDWxIJrodQ7Hf\nOVTyjpricdOCEx0Dm5yU/JWbsEl9/x4HQU0CQGr1I1id+L0wFwaYIGv9GOXTt3TV\nbRC4Na+A0ufZsGBOvEjdxDPhXO3/Ycx/p85eZW4mnjKd+Gykql7PCsJGjOECQCXN\nsvTE/kdG8OKijt+T+gf1k4fgjREPPy/kH43MIhsMQ9SQPD3oohNvJEY/u8XY7fuT\n5/uFYp++EfazdG1519UCQBnbEG7raU0y+1BHlHhxpX0Wg8uJdf9M8iI47oK8a4/A\n8+JEeiN3f56gdrKjScDviTIFgnFyZTMjLWhYWwzZdLY=\n-----END RSA PRIVATE KEY-----\n'
# # signatureStr, publickey = CCrypto.signature('test','hello world1','he')
# signatureStr, publickey = CCrypto.signature('hello world1',privatekey)
# print(CCrypto.verifySignature('hello world1',signatureStr, publickey))
# with open("test/209975d519682e858ab82f06a1eaa500bf32a836-private.pem") as f:
#         key = f.read()
#         print(key.encode())
# a=b''
# # a=b'-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDKpfCC/1U8zRVzNOsl8zDQ9AJeWcAEeQ7U9BEk3ZIq1OFhETVu\n2+aMvOJXwR0AM5lrGXQrOTd4slb2RD4JoBlIErpv3p/ZHb+qmbBnMwVWdsJBikdt\nqGXiP/HhvEnn+CJno9vbkbZW4JjJJUVXHhq6u4lpXHU4egaVpv5tsA4r4wIDAQAB\nAoGAP8y4iPWMR2Ul4KyDb+I9tztrV3sYKhBW7BKfJyUe9J8rCd1aHjnbPunktM4W\nrE6SeZZ87XLJFRXIrSXVBkDCVE/kM/L0D17L11ukitoxcSTLWNsKmf409h3Bifgx\nB7AjvwB3ab0PH3JcMNU4xuL8byHhGS6VvLWb6D0lfohN24kCQQDVw+84pntyh7JT\nfSqBPOUbT3t59Yo3q90mWZRJXEmrPklIB6J/X3z5lZoxN1Jq3ISPCXGCWlEoJS7Q\nAWgVbh5/AkEA8q+1WkboVa4V4mv7Yrt8QqPZU9W0CM23/ffXm4/oTs8PxwkQKKyU\nVCB2VwIE5tDzjhr1oo7+wMHHAhg8L66InQJBAINvfd9vPegl11fOVhwwvQ4VyO4s\nM1gXrFqwKaURwZoxKg3H4/o9VDKB8dThFyPtgvQP8mMb9Vqhwi7TLpQ+qTECQQCK\nL7y+8+M1blPtwni45nLB61RDZUsHPERJK4esf4vS3BpqxeFal7I6GOXpcy/hUhds\n0jMN5ghvL6emrLAQonwNAkEAjivB6566E+0xpNUjIlaHzQqAfV/Xriq2kpQeVSr1\n2kgdO1u232IzvAPCy0O5gCA/PmTslxsfZg0PWkd8mUsFAg==\n-----END RSA PRIVATE KEY-----'
# CCrypto.produceKey1('test')  